<?php
require_once "QH.Config.Interface.php";
require_once "QH.Data.php";
require_once "QH.Exception.php";

/**
 * 接口访问类，包含所有API列表的封装，类中方法为static方法，
 * 每个接口有默认超时时间6s
 * @author Zhang Xingliang
 */
class QHApi
{
    /**
     * SDK版本号
     * @var string
     */
    public static $VERSION = "1.0.10";

    /**
     * http请求前统一数据签名处理
     * @param QHConfigInterface $url 接口连接后缀
     * @param QHConfigInterface $config 配置对象
     * @param QHBaseEntity $entity
     * @param int $timeOut
     * @return array() 成功时返回，其他抛异常
     */
    public static function baseRequest($url, $config, $entity, $timeOut = 6)
    {
        $entity->setAppId($config->getAppId());//渠道的key
        $entity->setNonceStr(self::getNonceStr());//随机字符串
        $entity->setTimeStamp(time());//随机字符串
        $entity->setSign($config);//签名

        $response = self::requestFormData($url, $config, $entity->getValues(), $timeOut);
        return QHResults::Init($config, $response, true);
    }

    /**
     * 查询任务分类
     *  区分阅读任务与关注任务的权限，判断可以查看那一种任务。如果进开通阅读权限则对接阅读权限有效，对接关注任务无效，反之一样。
     *  若两种权限都开通则对接哪一个可以宅前端展示哪一个，也可以两个都展示
     * @param QHConfigInterface $config 配置对象
     * @param QHBaseEntity $entity
     * @param int $timeOut
     * @return array() 成功时返回，其他抛异常
     */
    public static function getTaskClass($config, $entity, $timeOut = 6)
    {
        return self::baseRequest("/business/sdk/v1/read/get_task_class", $config, $entity, $timeOut);
    }

    /**
     *
     * 查询阅读任务列表，user_id 必传
     * @param QHConfigInterface $config 配置对象
     * @param QHBaseEntity $entity
     * @param int $timeOut
     * @return array() 成功时返回，其他抛异常
     * @throws QHException
     */
    public static function getTaskList($config, $entity, $timeOut = 6)
    {
        //检测必填参数
        QHException::validateParam($entity, 'user_id');
        return self::baseRequest("/business/sdk/v1/read/get_task_list", $config, $entity, $timeOut);
    }

    /**
     * 一键领取
     *  一键领取是用户领取任务的重要操作，若您使用我们的页面，在任务列表中即可在点击一键领取按键时调用此接口。
     *  如果不想使用我们的页面，也可以在您自己的页面中增加按键，调取此接口领取任务。
     * @param QHConfigInterface $config 配置对象
     * @param QHBaseEntity $entity
     * @param int $timeOut
     * @return array() 成功时返回，其他抛异常
     * @throws QHException
     */
    public static function getReadTask($config, $entity, $timeOut = 6)
    {
        //检测必填参数
        QHException::validateParam($entity, 'user_id');
        return self::baseRequest("/business/sdk/v1/read/one_click_collection", $config, $entity, $timeOut);
    }

    /**
     * 更新异步任务完成通知地址
     * @throws Exception
     */
    public static function updateNotifyUrl($config, $entity, $timeOut = 6)
    {
        //检测必填参数
        QHException::validateParam($entity, 'notify_url');
        return self::baseRequest("/business/sdk/v1/read/update_notify_url", $config, $entity, $timeOut);
    }

    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return string 产生的随机字符串
     */
    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 以post方式提交json到对应的接口url
     *
     * @param QHConfigInterface $config 配置对象
     * @param string $data 需要post的json数据
     * @param string $url url
     * @param int $second url执行超时时间，默认30s
     * @throws QHException
     */
    private static function requestJson($url, $config, $data, $second = 30)
    {
        $ch = curl_init();
        $curlVersion = curl_version();
        $ua = "QHSDK/" . self::$VERSION . " (" . PHP_OS . ") PHP/" . PHP_VERSION . " CURL/" . $curlVersion['version'] . " "
            . $config->getAppId();

        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        $this_header = array("content-type:application/json;charset=UTF-8");
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this_header);

        curl_setopt($ch, CURLOPT_URL, $config->getGateway() . $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);//严格校验
        curl_setopt($ch, CURLOPT_USERAGENT, $ua);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            QHException::ThrowQHException("curl出错，错误码:$error");
        }
    }

    /**
     * 直接输出json
     * @param string $data
     */
    public static function replyNotify($data)
    {
        echo $data;
    }

    /**
     * 以post方式提交form-data到对应的接口url
     *
     * @param QHConfigInterface $config 配置对象
     * @param string $data 需要post的form-data数据
     * @param string $url url
     * @param int $second url执行超时时间，默认30s
     * @throws QHException
     */
    private static function requestFormData($url, $config, $data, $second = 30)
    {
        $ch = curl_init();
        $curlVersion = curl_version();
        $ua = "QHSDK/" . self::$VERSION . " (" . PHP_OS . ") PHP/" . PHP_VERSION . " CURL/" . $curlVersion['version'] . " "
            . $config->getAppId();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        curl_setopt($ch, CURLOPT_URL, $config->getGateway() . $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);//严格校验
        curl_setopt($ch, CURLOPT_USERAGENT, $ua);
        //设置header
//        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("content-type:multipart/form-data;charset=UTF-8"));
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            QHException::ThrowQHException("curl出错，错误码:$error");
        }
    }

}
